/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-10-25     huger       the first version
 */

#include "app_io.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#define bool
#include <qled.h>
#undef bool

#ifdef __cplusplus
}
#endif /* __cplusplus */


#define DBG_TAG "io"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

const uint32_t foot_pin[7] = {
        GET_PIN(C, 4),
        GET_PIN(A,7),
        GET_PIN(A,6),
        GET_PIN(A,5),
        GET_PIN(A,4),
        GET_PIN(A,3),
        GET_PIN(A,2),
};

const uint32_t sensor_pin[2] = {
        GET_PIN(A,0),
        GET_PIN(A,1),
};

const uint32_t motor_stop_pin = GET_PIN(B,4);


const uint32_t rgb_pin[3]={
        GET_PIN(C,10),
        GET_PIN(C,11),
        GET_PIN(C,12),
};

const uint32_t eng_trg_pin[6]={
        GET_PIN(A,12),
        GET_PIN(A,11),
        GET_PIN(A,10),
        GET_PIN(A,9),
        GET_PIN(A,8),
        GET_PIN(C,9),
};


const uint32_t beep_pin = GET_PIN(C, 5);


static bitfilter_t foot_filter[7];
static bitfilter_t sensor_filter[2];
static bitfilter_t motor_stop_filter;

iomap gpio_map;

static void input_fulsh(iomap* map)
{
    int bitval = 0;

    for(uint32_t i = 0 ; i < sizeof(foot_filter) / sizeof(uint32_t); i++)
    {
        bitval = rt_pin_read(foot_pin[i]);
        mod_bitfilter_poll(bitval, foot_filter + i);

        map->foot_st[i] = mod_bitfilter_state(foot_filter + i);
    }

    for(uint32_t i = 0 ; i < sizeof(sensor_filter) / sizeof(uint32_t); i++)
    {
        bitval = rt_pin_read(sensor_pin[i]);
        mod_bitfilter_poll(bitval, sensor_filter + i);

        map->sensor_st[i] = mod_bitfilter_state(sensor_filter + i);
    }

    bitval = rt_pin_read(motor_stop_pin);
    mod_bitfilter_poll(bitval, &motor_stop_filter);
    map->motor_stop_st = mod_bitfilter_state(&motor_stop_filter);

#if 0

    for(uint8_t i=0;i<4;i=i+2)
    {
        if((map->foot_st[i] || map->foot_st[i+1]) && map->sensor_st[i/2]) {
            if(map->foot_st[i])map->eng_trg_st[i]=1;if(map->foot_st[i+1])map->eng_trg_st[i+1]=1;
        }
        else{ map->eng_trg_st[i]=0 ;map->eng_trg_st[i+1]=0 ;}
    }
    for(uint8_t i =4;i<6;i++){ if(map->foot_st[i])map->eng_trg_st[i]=1;else map->eng_trg_st[i]=0;}
#endif

#if 0
    for(uint8_t i =0;i<6;i++){ if(map->foot_st[i])map->eng_trg_st[i]=1;else map->eng_trg_st[i]=0;}
#endif
}

static void output_fulsh(iomap* map)
{
    uint32_t i;
    rt_pin_write(beep_pin, map->beep_st);

    for(i =0;i < sizeof(eng_trg_pin)/sizeof(uint32_t);i++) rt_pin_write(eng_trg_pin[i], map->eng_trg_st[i]);

    if((map->rgb.style_backup != map->rgb.style)||(map->rgb.freq_backup != map->rgb.freq))
    {
        map->rgb.style_backup = map->rgb.style;
        map->rgb.freq_backup = map->rgb.freq;
        int time = 1000.0f / map->rgb.freq / 2;

        if(map->rgb.style & 0x04){
            qled_set_blink(rgb_pin[2], time, time);
        }
        else
        {
            qled_set_off(rgb_pin[2]);
        }

        if(map->rgb.style & 0x02)
        {
            qled_set_blink(rgb_pin[1], time, time);
        }
        else
        {
            qled_set_off(rgb_pin[1]);
        }

        if(map->rgb.style & 0x01)
        {
            qled_set_blink(rgb_pin[0], time, time);
        }
        else
        {
            qled_set_off(rgb_pin[0]);
        }
    }


}

static void app_io_thread_entry(void* param)
{
    while(1)
    {

        iomap map = {0};

        rt_enter_critical();
        memcpy(&map, param, sizeof(iomap));
        rt_exit_critical();

        input_fulsh(&map);
        output_fulsh(&map);

        rt_enter_critical();
        memcpy(param, &map, sizeof(iomap));
        rt_exit_critical();

        rt_thread_mdelay(10);
    }
}

void app_io_init(void)
{
    uint32_t i;
    iomap* map = &gpio_map;
    //变量初始化
    map->beep_st=0;
    map->rgb.style = 2;map->rgb.freq=1;     //1  red  2 green  4 blue

    for(i=0; i< sizeof(eng_trg_pin)/sizeof(uint32_t);i++) map->eng_trg_st[i]=0;

    //初始化滤波结构体
    for(i = 0 ; i < sizeof(foot_filter) / sizeof(bitfilter_t); i++)
        mod_bitfilter_init(foot_filter + i, 5, 5);

    for(i = 0 ; i < sizeof(sensor_filter) / sizeof(bitfilter_t); i++)
        mod_bitfilter_init(sensor_filter + i, 5, 5);

    mod_bitfilter_init(&motor_stop_filter , 5, 5);
    //输入引脚初始化
    for(i = 0 ; i < sizeof(foot_pin) / sizeof(uint32_t); i++)
        rt_pin_mode(foot_pin[i], PIN_MODE_INPUT);

    for(i = 0 ; i < sizeof(sensor_pin) / sizeof(uint32_t); i++)
        rt_pin_mode(sensor_pin[i], PIN_MODE_INPUT);

    rt_pin_mode(motor_stop_pin, PIN_MODE_INPUT);


    for(int i = 0; i < 30; i++)
    {
        input_fulsh(map);
        rt_thread_mdelay(5);
    }

//    output_fulsh(map);

    //输出引脚初始化

    for(i = 0 ; i < sizeof(eng_trg_pin) / sizeof(uint32_t); i++)
    {
        uint32_t* p= (uint32_t*)eng_trg_pin;
        rt_pin_mode((rt_base_t)p[i], PIN_MODE_OUTPUT);
    }
    for(i = 0 ; i < sizeof(rgb_pin) / sizeof(uint32_t); i++)
    {
        uint32_t* p= (uint32_t*)rgb_pin;
        rt_pin_mode((rt_base_t)p[i], PIN_MODE_OUTPUT);
        qled_add((int)p[i], 0);
        qled_set_off((int)p[i]);
    }
    rt_pin_mode(beep_pin, PIN_MODE_OUTPUT);

    output_fulsh(map);

    rt_thread_t thread = rt_thread_create("io", app_io_thread_entry, map,
                                  1024, 14, 20);

    if (thread == RT_NULL)
    {
        LOG_D("io_thread error");
    }

    rt_thread_startup(thread);

}

void app_io_get_gpio_map(iomap* map)
{
    rt_enter_critical();
    memcpy(map, &gpio_map, sizeof(iomap));
    rt_exit_critical();
}

void app_io_set_gpio_map(iomap* map)
{
    rt_enter_critical();
    memcpy(&gpio_map, map, sizeof(iomap));
    rt_exit_critical();
}

static int dbg_io_info(int argc, char *argv[])
{
    uint32_t i;
    for(i = 0 ; i < sizeof(gpio_map.foot_st) / sizeof(uint8_t); i++)
        LOG_I("hall_st[%d] = %d", i, gpio_map.foot_st[i]);

    for(i = 0 ; i < sizeof(gpio_map.sensor_st) / sizeof(uint8_t); i++)
        LOG_I("key_st[%d] = %d", i, gpio_map.sensor_st[i]);

    LOG_I("motor_stop_st = %d", i, gpio_map.motor_stop_st);

//    LOG_I("fan_pow = %d", gpio_map.fan_pow);
    return RT_EOK;
}
MSH_CMD_EXPORT(dbg_io_info, 获取io信息);
